﻿
var AzureHelper = new function() {
    for (var e = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split(""), i = 64, d = []; i; ) d[e[--i]] = i;

    this.AddHeaders = function(xmlhttp, AccountName, Storage, Command, SharedKey, Path) {
        xmlhttp.open("GET", "http://" + AccountName + "." + Storage + "/" + Path + "?" + Command + "&maxresults=50&timeout=30&nocache=" + Math.floor(Math.random() * 1000000001), true);
        //set the date header
        var curdate = new Date()
        var DateGMT = this.toAzureDate(curdate);
        xmlhttp.setRequestHeader("x-ms-date", DateGMT);
        //can we do the auth header?
        var authorizationString = "SharedKey " + AccountName + ":" + this.getSignature("GET", DateGMT, Command, AccountName, SharedKey, Path);
        xmlhttp.setRequestHeader("Authorization", authorizationString);
    },

    this.getSignature = function(VERB, Date, Command, AccountName, SharedKey, Path) {
        var key = this.base64d(SharedKey);
        var ContentMD5 = "";
        var ContentType = "";
        var CanonicalizedHeaders = "x-ms-date:" + Date + "\n";
        var CanonicalizedResource = "/" + AccountName + "/" + Path + "?" + Command;
        var StringToSign = VERB + "\n" +
               ContentMD5 + "\n" +
               ContentType + "\n" +
               "" + "\n" +
               CanonicalizedHeaders +
               CanonicalizedResource;

        HMAC_SHA256_init(key);
        HMAC_SHA256_write(StringToSign);
        var res = HMAC_SHA256_finalize();
        return this.base64e(res);
    },

    this.base64e = function(A) {
        var s = [], i = 0, j = 0, n, l = A.length, m = l % 3;
        while (i < l) s[j++] = e[(n = A[i++] << 16 | A[i++] << 8 | A[i++]) >> 18 & 63] + e[n >> 12 & 63] + e[n >> 6 & 63] + e[n & 63];
        if (m) for (s[--j] = s[j].substr(0, s[j].length - (m = 3 - m)); m--; ) s[j] += "=";
        return s.join("")
    },
    
    this.base64d = function(s) {
        var A = [], i = 0, j = 0, l = (s = s.replace(/[^A-Za-z\d\+\/]/g, "")).length, m = l & 3, n;
        while (i < l) A[j++] = (n = d[s.charAt(i++)] << 18 | d[s.charAt(i++)] << 12 | d[s.charAt(i++)] << 6 | d[s.charAt(i++)]) >> 16, A[j++] = n >> 8 & 255, A[j++] = n & 255;
        A.length -= [0, 0, 2, 1][m];
        return A
    },

    this.toAzureDate = function(date) {
        //format is very strict:
        //"Thu, 05 Feb 2009 05:36:56 GMT"
        var ret = "";
        switch (date.getUTCDay()) {
            case 0: ret += "Sun, "; break;
            case 1: ret += "Mon, "; break;
            case 2: ret += "Tue, "; break;
            case 3: ret += "Wed, "; break;
            case 4: ret += "Thu, "; break;
            case 5: ret += "Fri, "; break;
            case 6: ret += "Sat, "; break;
        }
        ret += this.PadDigits(date.getUTCDate(), 2);
        switch (date.getUTCMonth()) {
            case 0: ret += " Jan "; break;
            case 1: ret += " Feb "; break;
            case 2: ret += " Mar "; break;
            case 3: ret += " Apr "; break;
            case 4: ret += " May "; break;
            case 5: ret += " Jun "; break;
            case 6: ret += " Jul "; break;
            case 7: ret += " Aug "; break;
            case 8: ret += " Sep "; break;
            case 9: ret += " Oct "; break;
            case 10: ret += " Nov "; break;
            case 11: ret += " Dec "; break;
        }
        ret += date.getUTCFullYear();
        ret += " ";
        ret += this.PadDigits(date.getUTCHours(), 2);
        ret += ":";
        ret += this.PadDigits(date.getUTCMinutes(), 2);
        ret += ":";
        ret += this.PadDigits(date.getUTCSeconds(), 2);
        ret += " GMT";
        return ret;
    },

    this.PadDigits = function(n, totalDigits) {
        n = n.toString();
        var pd = '';
        if (totalDigits > n.length) {
            for (i = 0; i < (totalDigits - n.length); i++) {
                pd += '0';
            }
        }
        return pd + n.toString();
    }

};